package com.ganmiao.filter;

import com.ganmiao.constant.AuthConstants;
import com.ganmiao.exception.DefaultBusinessException;
import com.ganmiao.resp.ResponseCode;
import com.ganmiao.utils.IpUtil;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Component;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.concurrent.TimeUnit;

/**
 * @Author calms
 * @Date 2024/2/26
 * @Desc
 */
@Component
public class UserUrlInterceptor implements HandlerInterceptor {

    private static final int time = AuthConstants.TIME;
    private static final int count = AuthConstants.COUNT;

    @Autowired
    private RedisTemplate<String,String> redisTemplate;


    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        // 获取请求的url
        String url = request.getRequestURI();
        String ip = IpUtil.getIpAddr(request);

        StringBuilder sb = new StringBuilder();
        sb.append("crazeidea:").append(ip).append(url);
        // 先查询redis中是否有这个键
        String key = sb.toString().replaceAll("/", ".");
        String value = get(key);
        if (StringUtils.isBlank(value)) {
            // 为空则插入新数据
            set(key, "1", time);
        } else {
            if (Integer.parseInt(value) < count) {
                // 没有超过就累加
                long redisTime = getExpire(key);
                set(key, (Integer.parseInt(value) + 1) + "", Math.toIntExact(redisTime));
            } else {
                // 超过访问次数
                String cou = get(ip);
                if (StringUtils.isBlank(cou)) {
                    setNoTime(ip, "1");
                } else {
                    if (Integer.parseInt(cou) <= 5) {
                        setNoTime(ip, (Integer.parseInt(cou) + 1) + "");
                    } else {
                        // 超过访问次数 5次以上 加入黑名单  删除redis
                        del(ip);
                    }
                }
                throw new DefaultBusinessException("您的操作频繁", ResponseCode.BUSINESS_EXCEPTION);
            }
        }
        return true;
    }

    @Override
    public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler,
                           ModelAndView modelAndView) throws Exception {

    }

    @Override
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex)
            throws Exception {

    }


    // 根据key获取value
    public String get(String key) {
        return this.redisTemplate.opsForValue().get(key);
    }

    // 根据key删除数据
    public void del(String key) {
        boolean boo = this.redisTemplate.hasKey(key);
        if (boo) {
            this.redisTemplate.delete(key);
        }
    }

    // 向redis存入数据
    public void setNoTime(String key, String value) {
        redisTemplate.opsForValue().set(key, value);
    }

    // 向redis存入数据 带失效时间
    public void set (String key, String value, int redisTime) {
        redisTemplate.opsForValue().set(key, value);
        redisTemplate.expire(key, redisTime, TimeUnit.MILLISECONDS);
    }

    // 获取redis当前键的失效时间
    public Long getExpire(String key) {
        if (null == key) {
            throw new  DefaultBusinessException( "key or TomeUnit 不能为空",ResponseCode.FAIL);
        }
        return redisTemplate.getExpire(key, TimeUnit.MILLISECONDS);
    }

}